perm filename CURVE.SAI[SYS,HE]2 blob sn#013500 filedate 1972-11-20 generic text, type T, neo UTF8
COMMENT ⊗   VALID 00012 PAGES 
RECORD PAGE   DESCRIPTION
 00001 00001
 00003 00002	ENTRY CURVE1
 00005 00003	⊃	FIND A POINT ON LINE CLOSEST TO X,Y
 00007 00004	⊃	arrays and variables which control processing:
 00011 00005	⊃	MOVE POINTS NEAR CORNERS TO CLOSEST LINE
 00014 00006	⊃	MAKE A NEW LINE CONNECTING PARALLEL SEGMENTS
 00016 00007	⊃	HERE WE CURVE FIT ONE SEGMENT
 00018 00008		⊃	DISPLAY LINES FIT THROUGH ROW INDEX
 00020 00009		⊃	PASS 1, BREAK OUTLINE INTO SHORT SEGMENTS
 00024 00010		⊃	COMBINE SMALL SEGMENTS USING TOLER2
 00027 00011		⊃	COMPUTE NEW CORNERS
 00032 00012	⊃	STORE DATA IN OUTPUT ARRAY
 00035 ENDMK
⊗;
ENTRY CURVE1;
BEGIN "CURVE"
REQUIRE "PREAMB.SAI[SYS,HE]" SOURCE_FILE;
REQUIRE "DPYSUB.HDR[SYS,HE]" SOURCE_FILE;
REQUIRE "MISCUR" LOAD_MODULE;
REQUIRE "SQRT[SYS,HE]" LOAD_MODULE;
REQUIRE 500 STRING_SPACE;
REQUIRE "HELIB.REL[1,3]" LIBRARY;

INTERNAL REAL TOLER,MINLEN,TOLER2,CORDIF,CORMX;
INTERNAL BOOLEAN XDEB, DD_DISP, XDMP, DISCUR;
DEFINE SAFEX="SAFE",SMAX="100",⊃="COMMENT",CRLF="'15&'12";
REAL X,Y, XX, YY;
INTEGER DEND;
INTERNAL INTEGER FRAMEX;
EXTERNAL INTEGER FRAMEY;
SAFEX INTEGER ARRAY DISPL[1:300];

FORWARD PROCEDURE CUR2(REFERENCE INTEGER SCNT;SAFEX REAL ARRAY D,ODAT;
	SAFEX INTEGER ARRAY JOIN;INTEGER DSTR,S_MAX);
EXTERNAL PROCEDURE FADCHG(REAL X,Y; PROCEDURE PROC);
EXTERNAL PROCEDURE FRDCHG(REAL X,Y; PROCEDURE PROC);
EXTERNAL PROCEDURE DISP(REAL ARRAY D);
EXTERNAL REAL PROCEDURE SQRT(REAL X);

INTERNAL INTEGER PROCEDURE CUR1(SAFEX REAL ARRAY D,LINE;
		SAFEX INTEGER ARRAY JOIN;REFERENCE INTEGER SCNT,S_MAX);
	BEGIN INTEGER STRT;
	TOLER←0.2;
	TOLER2←0.7;
	MINLEN←5.0;
	CORDIF ← 150.0;
	CORMX ← 1000.0;
	SCNT ← 0;
	STRT ← 1;
	DO	BEGIN
		CUR2(SCNT,D,LINE,JOIN,STRT,S_MAX);
		STRT ← D[STRT,2];
		END UNTIL ¬STRT;
	RETURN(IF SCNT<4 THEN -2 ELSE 0);
	END;
⊃	FIND A POINT ON LINE CLOSEST TO X,Y;

SIMPLE PROCEDURE GETPNT(REAL X,Y,A,B,C; REFERENCE REAL XX, YY);
	BEGIN
	IF ABS(A)>ABS(B) THEN
		BEGIN
		YY ← (-A*B*X+A↑2*Y+B*C)/(A↑2+B↑2);
		XX ← (C-B*Y)/A;
		END ELSE BEGIN
		XX ← (A*C+B↑2*X-A*B*Y)/(A↑2+B↑2);
		YY ← (C-A*X)/B;
		END;
	END;

⊃	DRAW AN ARROW_DPY;

SIMPLE INTERNAL PROCEDURE ARROW_DPY(REAL X,Y);
	BEGIN
	DPYBRT(3);
	FADCHG(X,Y,AIVECT);
	RVECT(60,0);
	RIVECT(-60,0);
	RVECT(20,14);
	RIVECT(0,-28);
	RVECT(-20,14);
	DPYBRT(7);
	END;

⊃	COMPUTE COEFICIENTS OF AX+BY=C;

EXTERNAL PROCEDURE COEF(SAFEX REAL ARRAY X);

⊃	COMPUTE LEAST SQUARES ERROR OF FIT AND RETURN;

EXTERNAL REAL PROCEDURE ERROR(SAFEX REAL ARRAY X);

⊃	CALCULATE NEW CORNER POSITION. TRUE IF CORNER
	EXISTS, FALSE IF LINES PARALLEL;

SIMPLE BOOLEAN PROCEDURE CORNER_CUR(SAFEX REAL ARRAY A1,A2;
		REFERENCE REAL X,Y);
	BEGIN REAL DENOM;
	IF ABS(DENOM←A1[7]*A2[8]-A1[8]*A2[7])<.001 THEN RETURN(FALSE);
	X ← (A2[8]*A1[9]-A1[8]*A2[9])/DENOM;
	Y ← (A1[7]*A2[9]-A2[7]*A1[9])/DENOM;
	RETURN(TRUE);
	END;
⊃	arrays and variables which control processing:

	D contains the raw edge points from the edge follower in the format
		described under the GET_DATA command.  Here, DSTR points to
		the start of the current block (the first coords in DSTR+1)
		and DEND points to the end of the block.  In between are the
		X,Y coordinate pairs.
	SUMS contains the output of pass 1, one seqment per row.  There are
		thirteen columns per row filled as follows:
		1-6 are the sums X, Y, X↑2, Y↑2, XY, and N
		7-9 are the line coefficients A, B, and C
		10-11 are pointers to the coords of the ends of the line
	SEGS is used in pass one to indicate breaks in the segment
		Each row points into D to the starting and ending
		coordinates of the  partial segment.
	INDEX is the last used row of SUMS
	SIND is the last used row of SEGS (and the one being processed)
	LOOP is TRUE is the initial segment was a closed curve
	LINE is the output array containing the coordinates of the lines
	JOIN tells which endpoints in LINE are linked
	SCNT is the maximum index of LINE
	TEMP,T1,T2 hold rows of SUMS while being processed in later passes
	COUT holds the computed coordinates during pass 3
	;

SIMPLE INTERNAL PROCEDURE CURVON;
	BEGIN INTEGER I;
	OUTSTR("DISPLAY?");
	IF INCHWL="Y" THEN
		BEGIN
		DISCUR ← TRUE;
		IF ¬RUN THEN DPYTYP(-150,2,6);
		END ELSE BEGIN
		RELPOG(FRAMEX);
		RELPOG(FRAMEY);
		END;
	OUTSTR("DUMP?");
	IF INCHWL="Y" THEN
		BEGIN
		OPEN(3,"DSK",0,0,2,100,I,I);
		ENTER(3,"CURVE.DBG",I);
		XDMP ← TRUE;
		END;
	END;

SIMPLE INTERNAL PROCEDURE CUROFF;
	BEGIN
	DISCUR ← XDMP ← XDEB ← FALSE;
	HYDPOG(FRAMEX);
	HYDPOG(FRAMEY);
	RELEASE(3);
	END;
⊃	MOVE POINTS NEAR CORNERS TO CLOSEST LINE;

PROCEDURE CORFIX(SAFEX REAL ARRAY F, L, D; INTEGER STR);
	BEGIN SAFEX REAL ARRAY T[1:11];
	BOOLEAN TOF;
	INTEGER P1, P2, INC, CNT;
	REAL E1, E2, X, Y, A, B, C;
	P1 ← F[11];
	X ← D[P1,1];
	Y ← D[P1,2];
	E1←ABS(((A←F[7])*X+(B←F[8])*Y-F[9])/SQRT(A↑2+B↑2));
	E2←ABS(((A←L[7])*X+(B←L[8])*Y-L[9])/SQRT(A↑2+B↑2));
	INC ← 1;
	IF ¬(TOF←E1<E2) THEN
		BEGIN ARRTRAN(T,F);ARRTRAN(F,L);ARRTRAN(L,T);INC←-1;END;
	WHILE TRUE DO
		BEGIN
		L[1] ← L[1]-X;
		L[2] ← L[2]-Y;
		L[3] ← L[3]-X↑2;
		L[4] ← L[4]-Y↑2;
		L[5] ← L[5]-X*Y;
		L[6] ← L[6]-1.0;
		COEF(L);
		P1 ← P1+INC;
		IF P1>DEND THEN P1←STR+1 ELSE IF P1=STR THEN P1←DEND;
		IF ¬L[6] THEN DONE;
		X ← D[P1,1];
		Y ← D[P1,2];
		E1←ABS(((A←F[7])*X+(B←F[8])*Y-F[9])/SQRT(A↑2+B↑2));
		E2←ABS(((A←L[7])*X+(B←L[8])*Y-L[9])/SQRT(A↑2+B↑2));
		IF E1>E2 THEN DONE;
		IF E1<1.0 THEN
			BEGIN "ADDON"
			F[1] ← F[1]+X;
			F[2] ← F[2]+Y;
			F[3] ← F[3]+X↑2;
			F[4] ← F[4]+Y↑2;
			F[5] ← F[5]+X*Y;
			F[6] ← F[6]+1.0;
			COEF(F);
			END "ADDON";
		END;
	IF ¬TOF THEN BEGIN ARRTRAN(T,F);ARRTRAN(F,L);ARRTRAN(L,T);END;
	P2 ← P1-INC;
	IF P2>DEND THEN P2←STR+1 ELSE IF P2=STR THEN P2←DEND;
	F[11] ← IF TOF THEN P2 ELSE P1;
	L[10] ← IF TOF THEN P1 ELSE P2;
	IF F[6]≤1.0 THEN F[6] ←0.0;
	IF L[6]≤1.0 THEN L[6] ←0.0;
	RETURN;
	END;
⊃	MAKE A NEW LINE CONNECTING PARALLEL SEGMENTS;

BOOLEAN PROCEDURE MAKLIN(SAFEX REAL ARRAY A,B,C,D; INTEGER STR);
	BEGIN INTEGER P1, P2, P3, P4;
	REAL X, Y, XQ, YQ, XY, N;

	SIMPLE BOOLEAN PROCEDURE PROC(INTEGER P;REAL ARRAY Z,Q);
		BEGIN REAL AA, BB, E, XX, YY;
		XX ← Q[P,1];
		YY ← Q[P,2];
		E←ABS(((AA←Z[7])*XX+(BB←Z[8])*YY-Z[9])/SQRT(AA↑2+BB↑2));
		IF E<1.0 THEN RETURN(TRUE);
		X ← X+XX;
		Y ← Y+YY;
		XQ ← XQ+XX↑2;
		YQ ← YQ+YY↑2;
		XY ← XY+XX*YY;
		N ← N+1.0;
		Z[1] ← Z[1] -XX;
		Z[2] ← Z[2] -YY;
		Z[3] ← Z[3] -XX↑2;
		Z[4] ← Z[4] -YY↑2;
		Z[5] ← Z[5] -YY*XX;
		IF (Z[6]←Z[6]-1.0)≤0 THEN RETURN(TRUE);
		COEF(Z);
		RETURN(FALSE);
		END;

	X ← Y ← XQ ← YQ ← XY ← N ← 0;
	P1 ← A[11]; P2 ← B[10]; P3 ← A[10]; P4 ← B[11];
	DO	BEGIN "SUM1"
		IF PROC(P1,A,D) THEN DONE;
		IF (P1←P1-1)≤STR THEN P1←DEND;
		END "SUM1" UNTIL P1=P3;
	DO	BEGIN "SUM2"
		IF PROC(P2,B,D) THEN DONE;
		IF (P2←P2+1)>DEND THEN P2←STR+1;
		END "SUM2" UNTIL P2=P4;
	IF N<1.5 THEN RETURN(FALSE);
	C[1] ← X;
	C[2] ← Y;
	C[3] ← XQ;
	C[4] ← YQ;
	C[5] ← XY;
	C[6] ← N;
	COEF(C);
	A[11] ← P1;
	B[10] ← P2;
	C[10] ← IF (P1+1)>DEND THEN STR+1 ELSE P1+1;
	C[11] ← IF (P2-1)≤STR THEN DEND ELSE P2-1;
	RETURN(TRUE);
	END;
⊃	HERE WE CURVE FIT ONE SEGMENT;

PROCEDURE CUR2(REFERENCE INTEGER SCNT;SAFEX REAL ARRAY D, LINE;
		SAFEX INTEGER ARRAY JOIN;INTEGER DSTR,S_MAX);
	BEGIN BOOLEAN LOOP, COMB, HALT;
	REAL EX, EY, E1, E2, EPS, LERR, AX, AY, X1, Y1;
	SAFEX REAL ARRAY SUMS[1:SMAX,1:11], TEMP,T1,T2,T3[1:11];
	SAFEX INTEGER ARRAY SEGS[1:SMAX,1:2];
	INTEGER INDEX, I, J, K, DPNT, SIND, PT1, PT2, L;
	LABEL L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L13;

	⊃	RETURN INDEX FOR COORDS FURTHEST FROM THE LINE THROUGH
		THE ENDPOINTS;

	INTEGER PROCEDURE GETMAX(INTEGER S,E);
		BEGIN REAL A,B,C,X1,X2,Y1,Y2,DENOM,M,T;
		EXTERNAL INTEGER PROCEDURE LOOP1(REAL ARRAY D;
			REAL A,B,C,DENOM;INTEGER I,DSTR,DEND,E);
		INTEGER I,J,K;
		X1 ← D[S,1];
		Y1 ← D[S,2];
		X2 ← D[E,1];
		Y2 ← D[E,2];
		A ← Y1-Y2;
		B ← X2-X1;
		C ← X1*Y2-X2*Y1;
		DENOM ← SQRT(A↑2+B↑2);
		I ← S-1;
		J ← LOOP1(D,A,B,C,DENOM,I,DSTR,DEND,E);
		IF ¬J THEN USERERR(0,0,"GETMAX LOST BIG"&CRLF);
		RETURN(J);
		END;
	⊃	DISPLAY LINES FIT THROUGH ROW INDEX;

	PROCEDURE DEBDIS(REAL TOLER,EPS; INTEGER INDEX, PAS);
		BEGIN INTEGER I, J, K;
		REAL X, Y, A, B, C;
		IF DD_DISP THEN
			BEGIN
			RELPOG(FRAMEX);
			IF PAS=1 THEN DISP(D);
			END;
		IF FRAMEX<0 THEN FRAMEX ← GETPOG;
		DPYSET(DISPL);
		DPYBRT(7);
		DPYBIG(3);
		FADCHG(10.0,240.0,AIVECT);
		SETFORMAT(0,0);
		DPYSST("PASS "&CVS(PAS));
		SETFORMAT(7,4);
		DPYSST("    TOLER="&CVF(TOLER)&"     EPS="&CVF(EPS));
		FADCHG(0,0,AIVECT);
		FOR I←1 STEP 1 UNTIL INDEX DO
			BEGIN
			J ← SUMS[I,10];
			K ← SUMS[I,11];
			A ← SUMS[I,7];
			B ← SUMS[I,8];
			C ← SUMS[I,9];
			GETPNT(D[J,1],D[J,2],A,B,C,X,Y);
			FRDCHG(X,Y,RIVECT);
			GETPNT(D[K,1],D[K,2],A,B,C,X,Y);
			FRDCHG(X,Y,RVECT);
			END;
		END;
	⊃	PASS 1, BREAK OUTLINE INTO SHORT SEGMENTS;

	IF DISCUR THEN
		BEGIN
		OUTSTR("DEBUG PASS 1?"&CRLF);
		XDEB ← INCHWL="Y";
		END;
	INDEX ← 0;
	DEND ← DSTR+(I←ABS(D[DSTR,1]));
	LOOP ← D[DSTR,1]>0;
	IF (LOOP∧I<6)∨(¬LOOP∧I<3) THEN GO TO L2;
	IF LOOP THEN
		BEGIN "LOOP"
		PT1 ← DSTR+1;
		PT2 ← (DSTR+DEND) DIV 2;
		SEGS[2,2] ← SEGS[1,1] ← GETMAX(PT1,PT2);
		SEGS[2,1] ← SEGS[1,2] ← GETMAX(PT2, PT1);
		SIND ← 2;
		END "LOOP" ELSE BEGIN "NO"
		SEGS[SIND←1,1] ← DSTR+1;
		SEGS[SIND,2] ← DEND;
		END "NO";
L1:	DO	BEGIN "MAIN"
		EXTERNAL PROCEDURE LOOP2(REAL ARRAY TEMP,D;
			INTEGER I,PT2,DEND,DSTR);
		PT1 ← SEGS[SIND,1];
		PT2 ← SEGS[SIND,2];
		I ← PT1-1;
		LOOP2(TEMP,D,I,PT2,DEND,DSTR);
		EPS ← ABS(ERROR(TEMP))/TEMP[6];
		IF XDEB THEN
			BEGIN "D1"
			DEBDIS(TOLER,EPS,INDEX,1);
			FOR J←SIND STEP -1 UNTIL 1 DO
				BEGIN REAL A,B,C,E;
				I ← SEGS[J,1];
				K ← SEGS[J,2];
				A ← D[I,1];
				B ← D[I,2];
				IF J=SIND∨A≠C∨B≠E THEN FRDCHG(A,B,RIVECT);
				C ← D[K,1];
				E ← D[K,2];
				FRDCHG(C,E,RVECT);
				END;
			ARROW_DPY(D[PT1,1], D[PT1,2]);
			ARROW_DPY(D[PT2,1], D[PT2,2]);
			DPYOUT(FRAMEX);
			INCHWL;
			END "D1";
		IF EPS>TOLER THEN
			BEGIN "BREAK"
			IF (SIND←SIND+1)>SMAX THEN
				USERERR(0,0,"SEGS OVERFLOWED"&CRLF);
			SEGS[SIND,1] ← PT1;
			SEGS[SIND-1,1]←SEGS[SIND,2]←GETMAX(PT1,PT2);
			GO TO L1;
			END "BREAK";
		IF (INDEX←INDEX+1)>SMAX THEN
			USERERR(0,0,"SUM ARRAY OVERFLOW"&CRLF);
		TEMP[10] ← PT1;
		TEMP[11] ← PT2;
L13:		IF INDEX>1 THEN
			BEGIN "SAVE"
			ARRBLT(T1[1],SUMS[INDEX-1,1],11);
			CORFIX(T1,TEMP,D,DSTR);
			IF T1[6] THEN ARRBLT(SUMS[INDEX-1,1],T1[1],11)
				ELSE INDEX←INDEX-1;
			END "SAVE";
		IF TEMP[6] THEN ARRBLT(SUMS[INDEX,1],TEMP[1],11)
			ELSE INDEX←INDEX-1;
		END "MAIN" UNTIL ¬(SIND ← SIND-1);
	IF INDEX>1∧LOOP THEN
		BEGIN "FINISH"
		ARRBLT(T1[1],SUMS[1,1],11);
		ARRBLT(T2[1],SUMS[INDEX,1],11);
		CORFIX(T2,T1,D,DSTR);
		I←INDEX;
		IF T1[6] THEN ARRBLT(SUMS[1,1],T1[1],11) ELSE
			BEGIN
			I←1;
			INDEX←INDEX-1;
			END;
		IF T2[6] THEN ARRBLT(SUMS[I,1],T2[1],11) ELSE INDEX←INDEX-1;
		END "FINISH";
	⊃	COMBINE SMALL SEGMENTS USING TOLER2;

L2:	IF DISCUR THEN
		BEGIN
		OUTSTR("DEBUG PASS 2?"&CRLF);
		XDEB←INCHWL="Y";
		RELPOG(FRAMEY);
		END;
L8:	COMB ← FALSE;
	I←1;
	IF INDEX≤2 THEN GO TO L10;
	HALT ← FALSE;
L5:	J ← I;
	ARRBLT(T1[1],SUMS[I,1],11);
L7:	IF J=1∧HALT THEN GO TO L3;
	IF (I←I+1)>INDEX THEN
		BEGIN HALT←TRUE;
		IF LOOP THEN I←1 ELSE GO TO L3;
		END;
	ARRBLT(T2[1],SUMS[I,1],11);
L6:	FOR K←1 STEP 1 UNTIL 6 DO TEMP[K]←T1[K]+T2[K];
	TEMP[10]←T1[10];
	TEMP[11]←T2[11];
	IF (I←I+1)>INDEX THEN
		BEGIN
		HALT ← TRUE;
		IF LOOP THEN I←1 ELSE GO TO L4;
		END;
	ARRBLT(T3[1],SUMS[I,1],11);
	FOR K←1 STEP 1 UNTIL 6 DO T1[K]←T2[K]+T3[K];
	T1[10] ← T2[10];
	T1[11]←T3[11];
L4:	E1 ← ABS(ERROR(TEMP))/TEMP[6];
	E2 ← ABS(ERROR(T1))/T1[6];
	IF XDEB THEN
		BEGIN
		DEBDIS(TOLER2,E1,INDEX,2);
		FADCHG(250.0,240.0,AIVECT);
		DPYSST("EPS2= "&CVF(E2));
		ARROW_DPY(D[TEMP[10],1],D[TEMP[10],2]);
		IF HALT∧¬LOOP THEN
			ARROW_DPY(D[TEMP[11],1],D[TEMP[11],2]) ELSE
			ARROW_DPY(D[T1[11],1],D[T1[11],2]);
		DPYOUT(FRAMEX);
		INCHWL;
		END;
	IF E1<TOLER2∧((HALT∧¬LOOP)∨E2>E1) THEN
		BEGIN
		IF ¬HALT∧LOOP∧J=1 THEN GO TO L9;
		COMB ← TRUE;
		IF J<INDEX THEN
			BEGIN
			ARRBLT(SUMS[J,1],TEMP[1],11);
			IF J+1<INDEX THEN ARRBLT(SUMS[J+1,1],SUMS[J+2,1],
				(INDEX-J-1)*11);
			END ELSE BEGIN
			ARRBLT(SUMS[1,1],TEMP[1],11);
			J ← 1;
			END;
		IF (INDEX ← INDEX-1)<I THEN I←1;
		IF HALT∧¬LOOP THEN GO TO L3;
		ARRTRAN(T1,TEMP);
		I ← J;
		GO TO L7;
		END;
	IF ¬HALT∨LOOP THEN IF E2<TOLER2 THEN
		BEGIN
		ARRTRAN(T1,T2);
		ARRTRAN(T2,T3);
		IF (J←J+1)>INDEX THEN J←1;
		GO TO L6;
		END ELSE BEGIN
L9:		ARRTRAN(T1,T3);
		J←I;
		IF ¬HALT∨J>2 THEN GO TO L7;
		END;
L3:	IF COMB THEN GO TO L8;
	⊃	COMPUTE NEW CORNERS
		AND DELETE EXTRA SEGMENTS;

L10:	IF DISCUR THEN
		BEGIN
		OUTSTR("DEBUG PASS 3?"&CRLF);
		XDEB ← INCHWL="Y";
		END;
	IF INDEX<1∨(LOOP∧INDEX<3) THEN RETURN;
	IF FALSE THEN FOR I←1 STEP 1 UNTIL INDEX DO
	   IF SUMS[I,6]<MINLEN ∧(LOOP∨(I≠1∧I≠INDEX)) THEN
		BEGIN "SHORT"
		ARRBLT(TEMP[1],SUMS[IF I-1>0 THEN I-1 ELSE INDEX,1],11);
		ARRBLT(T1[1],SUMS[IF I+1>INDEX THEN 1 ELSE I+1,1],11);
		J ← SUMS[I,10];
		K ← SUMS[I,11];
		AX ← (D[J,1]+D[K,1])/2;
		AY ← (D[J,2]+D[K,2])/2;
		IF CORNER_CUR(TEMP,T1,X,Y)∨(E1←((X-AX)↑2+(Y-AY)↑2)<CORDIF)
			THEN BEGIN "DELETE"
			ARRBLT(SUMS[I,1],SUMS[I+1,1],(INDEX-I)*11);
			INDEX ← INDEX-1;
			IF XDEB THEN
				BEGIN "D2"
				DEBDIS(CORDIF,E1,INDEX,3);
				FADCHG(250.0,240.0,AIVECT);
				DPYSST("DELETED");
				ARROW_DPY(X,Y);
				DPYOUT(FRAMEX);
				INCHWL;
				END "D2";
			END "DELETE";
		END "SHORT";
	IF INDEX<1∨(LOOP∧INDEX<3) THEN RETURN;
		BEGIN "COMPUT" SAFEX REAL ARRAY COUT[1:INDEX+10,1:2];
		LABEL L12, L9;
		L ← 1;
		IF ¬LOOP THEN
			BEGIN "NOLOP"
			GETPNT(D[SUMS[1,10],1],D[SUMS[1,10],2],SUMS[1,7],
				SUMS[1,8],SUMS[1,9],COUT[1,1],COUT[1,2]);
			L ← L+1;
			GETPNT(D[SUMS[INDEX,11],1],D[SUMS[INDEX,11],2],
				SUMS[INDEX,7],SUMS[INDEX,8],SUMS[INDEX,9],
				XX,YY);
			END "NOLOP";
		IF INDEX=1 THEN IF SUMS[1,6]<4 THEN RETURN ELSE GO TO L9;
		FOR I←1 STEP 1 UNTIL INDEX-1 DO
			BEGIN "CORNER"
			J←I+1;
	L12:		ARRBLT(T1[1],SUMS[I,1],11);
			ARRBLT(T2[1],SUMS[J,1],11);
			IF CORNER_CUR(T1,T2,X,Y) THEN
				BEGIN "FIND"
				PT1 ← T2[10];
				PT2 ← T1[11];
				EX ← D[PT1,1];
				EY ← D[PT1,2];
				AX ← D[PT2,1];
				AY ← D[PT2,2];
				E1←(EX-AX)↑2+(EY-AY)↑2;
				IF E1>CORDIF THEN
					OUTSTR("BAD CORNER MATCH"&CRLF);
				E2 ← IF E1<2.0 THEN (AX-X)↑2+(AY-Y)↑2 ELSE
					(X-(AX+EX)/2)↑2+(Y-(AY+EY)/2)↑2;
				IF E2<CORDIF THEN
					BEGIN "GOOD"
					COUT[L,1] ← X;
					COUT[L,2] ← Y;
					END "GOOD" ELSE BEGIN "BAD"
					OUTSTR("BAD CORNER REJECTED"&
						CVF(E2)&'15&'12);
					IF E2>CORMX∧
						MAKLIN(T1,T2,TEMP,D,DSTR)∧
						CORNER_CUR(T1,TEMP,AX,AY)∧
						CORNER_CUR(TEMP,T2,EX,EY)
						THEN BEGIN "ADLINE"
						COUT[L,1] ← AX;
						COUT[L,2] ← AY;
						L ← L+1;
						COUT[L,1] ← EX;
						COUT[L,2] ← EY;
						END "ADLINE" ELSE BEGIN
						COUT[L,1] ← (EX+AX)/2;
						COUT[L,2] ← (EY+AY)/2;
						END;
					END "BAD";
				L ← L+1;
				END "FIND" ELSE BEGIN "NOF"
				FOR K←1 STEP 1 UNTIL 6 DO T1[K]←T1[K]+T2[K];
				T1[11] ← T2[11];
				COEF(T1);
				ARRBLT(SUMS[IF J=1 THEN J ELSE I,1],
					T1[1],11);
				ARRBLT(SUMS[I,1],SUMS[I+1,1],(INDEX-I)*11);
				INDEX ← INDEX-1;
				END "NOF";
			END "CORNER";
		IF INDEX=1 THEN GO TO L9;
		IF LOOP∧J>1 THEN BEGIN J←1;I←INDEX;GO TO L12;END;
		INDEX ← L-1;
L9:		IF INDEX<1∨(LOOP∧INDEX<3) THEN RETURN;
⊃	STORE DATA IN OUTPUT ARRAY;

		IF SCNT+INDEX+1>S_MAX THEN OUTSTR("ODAT OVERFLOW"&CRLF) ELSE
			BEGIN
			FOR I ← 1 STEP 1 UNTIL INDEX-1 DO
				BEGIN
				LINE[SCNT←SCNT+1,1] ← COUT[I,1];
				LINE[SCNT,2] ← COUT[I,2];
				LINE[SCNT,3] ← COUT[I+1,1];
				LINE[SCNT,4] ← COUT[I+1,2];
				JOIN[SCNT,1] ← I≠1∨LOOP;
				JOIN[SCNT,2] ← TRUE;
				END;
			LINE[SCNT←SCNT+1,1]←COUT[INDEX,1];
			LINE[SCNT,2]←COUT[INDEX,2];
			JOIN[SCNT,1]←TRUE;
			IF LOOP THEN
				BEGIN
				LINE[SCNT,3]←COUT[1,1];
				LINE[SCNT,4]←COUT[1,2];
				JOIN[SCNT,2]←TRUE;
				END ELSE BEGIN
				LINE[SCNT,3]←XX;
				LINE[SCNT,4]←YY;
				JOIN[SCNT,2]←FALSE;
				END;
			END;
		END "COMPUT";
	END;

END;